using AiQiuQuan.Sport.Model.Models;
using AiQiuQuan.Sport.WebApi.Repositories;
using Microsoft.EntityFrameworkCore;
using AiQiuQuan.Sport.Core;
using AiQiuQuan.Sport.WebApi.Core;
using AiQiuQuan.Sport.Model.Enums;

namespace AiQiuQuan.Sport.WebApi.Services.Impl
{
    /// <summary>
    /// 管理
    /// </summary>
    public class BaseUserService : IBaseUserService
    {
        private readonly ApiUrl _apiUrl;
        private readonly ICurrentInfo _currentInfo;
        private readonly IBaseUserRepository _baseUserRepository;
        private readonly IBaseUserExtendInfoRepository _baseUserExtendInfoRepository;
        private readonly IBaseUserTennisLevelConfigRepository _baseUserTennisLevelConfigRepository;
        private readonly IBaseUserVenueInfoRelationRepository _baseUserVenueInfoRelationRepository;
        private readonly ICoacherRepository _coacherRepository;
        private readonly IUserTokenService _userTokenService;
        private readonly IGameManageUserRepository _gameManageUserRepository;

        /// <summary>
        /// ctor
        /// </summary>
        public BaseUserService(
            ApiUrl apiUrl,
            ICurrentInfo currentInfo,
            IBaseUserRepository baseUserRepository,
            IBaseUserExtendInfoRepository baseUserExtendInfoRepository,
            IBaseUserTennisLevelConfigRepository baseUserTennisLevelConfigRepository,
            IBaseUserVenueInfoRelationRepository baseUserVenueInfoRelationRepository,
            ICoacherRepository coacherRepository,
            IUserTokenService userTokenService,
            IGameManageUserRepository gameManageUserRepository)
        {
            _apiUrl = apiUrl;
            _currentInfo = currentInfo;
            _baseUserRepository = baseUserRepository;
            _baseUserExtendInfoRepository = baseUserExtendInfoRepository;
            _baseUserTennisLevelConfigRepository = baseUserTennisLevelConfigRepository;
            _baseUserVenueInfoRelationRepository = baseUserVenueInfoRelationRepository;
            _coacherRepository = coacherRepository;
            _userTokenService = userTokenService;
            _gameManageUserRepository = gameManageUserRepository;
        }

        /// <summary>
        /// 登录
        /// </summary>
        public async Task<UserTokenResultDto> LoginAsync()
        {
            var request = new UserTokenRequestDto
            {
                UserId = Guid.Parse("966D3ACF-F170-4DC3-EF0A-08DA477F295A"),
                NickName = "天心",
                MiniProgramOpenId = "oxMwX5b49OSs3jmDkLlRo5257i6o"
            };
            var result = await _userTokenService.CreateTokenAsync(request);
            return result;
        }

        /// <summary>
        /// 查询一条记录
        /// </summary>
        public async Task<BaseUserDto> GetAsync(Guid id)
        {
            var queryable = from user in _baseUserRepository.AsNoTracking()
                            join tennis1 in _baseUserExtendInfoRepository.AsNoTracking()
                            on user.ID equals tennis1.ID into tennis1d
                            from tennis1 in tennis1d.DefaultIfEmpty()
                            join tennis2 in _baseUserTennisLevelConfigRepository.AsNoTracking()
                            on tennis1.BaseUserTennisLevelConfigID equals tennis2.ID into tennis2d
                            from tennis2 in tennis2d.DefaultIfEmpty()
                            where user.ID == id
                            select new BaseUserDto
                            {
                                ID = user.ID,
                                U_Code = user.U_Code,
                                U_NickName = user.U_NickName,
                                U_Headportrait = user.U_Headportrait,
                                U_RealName = user.U_RealName,
                                U_OpenId = user.U_OpenId,
                                U_Unionid = user.U_Unionid,
                                U_PhoneNum = user.U_PhoneNum,
                                U_IsCanWithdrawal = user.U_IsCanWithdrawal,
                                U_Birthday = user.U_Birthday,
                                U_WxOpenId = user.U_WxOpenId,
                                CardName = user.CardName,
                                U_Sex = user.U_Sex,
                                ProvinceID = user.ProvinceID,
                                U_P_Name = user.U_P_Name,
                                CityID = user.CityID,
                                U_C_Name = user.U_C_Name,
                                TennisLevel = tennis2.LevelName ?? "1.0",
                                TennisLevelId = tennis2.ID,
                                TennisLevelExplain = tennis2.LevelExplain,
                                CreateTime = user.CreateTime,
                            };
            var result = await queryable.FirstOrDefaultAsync();
            if (result != null)
            {
                result.IsSyncPhone = !string.IsNullOrWhiteSpace(result.U_PhoneNum);
                result.IsSyncUserInfo = !string.IsNullOrWhiteSpace(result.U_NickName);
            }

            return result;
        }

        /// <summary>
        /// 查询用户信息，含用户角色
        /// </summary>
        public async Task<BaseUserDto> QueryAsync(BaseUserRoleRequestDto request)
        {
            var queryable = from user in _baseUserRepository.AsNoTracking()
                            join tennis1 in _baseUserExtendInfoRepository.AsNoTracking()
                            on user.ID equals tennis1.ID into tennis1d
                            from tennis1 in tennis1d.DefaultIfEmpty()
                            join tennis2 in _baseUserTennisLevelConfigRepository.AsNoTracking()
                            on tennis1.BaseUserTennisLevelConfigID equals tennis2.ID into tennis2d
                            from tennis2 in tennis2d.DefaultIfEmpty()
                            where user.ID == _currentInfo.UserId
                            select new BaseUserDto
                            {
                                ID = user.ID,
                                U_Code = user.U_Code,
                                U_NickName = user.U_NickName,
                                U_Headportrait = user.U_Headportrait,
                                U_RealName = user.U_RealName,
                                U_OpenId = user.U_OpenId,
                                U_Unionid = user.U_Unionid,
                                U_PhoneNum = user.U_PhoneNum,
                                U_IsCanWithdrawal = user.U_IsCanWithdrawal,
                                U_Sex = user.U_Sex,
                                U_WxOpenId = user.U_WxOpenId,
                                CardName = user.CardName,
                                TennisLevel = tennis2.LevelName ?? "1.0",
                                CreateTime = user.CreateTime,
                                TennisLevelId = tennis2.ID,
                                TennisLevelExplain = tennis2.LevelExplain,
                                IsVenueManage = _baseUserVenueInfoRelationRepository.Any(m => m.BaseUserID == user.ID)
                            };
            var result = await queryable.FirstOrDefaultAsync();
            if (result != null)
            {
                result.IsSyncPhone = !string.IsNullOrWhiteSpace(result.U_PhoneNum);
                result.IsSyncUserInfo = !string.IsNullOrWhiteSpace(result.U_NickName);
                var coacher = await _coacherRepository.FirstOrDefaultAsync(m => m.UserId == result.ID);
                result.CoacherType = coacher == null ? CoacherTypeEnum.None : coacher.Type;
                result.IsGameManage = await _gameManageUserRepository.AnyAsync(m => m.UserId == result.ID);
            }

            return result;
        }

        /// <summary>
        /// 更新
        /// </summary>
        public async Task<UnaryResult> UpdateAsync(BaseUserUpdateDto request)
        {
            var user = await _baseUserRepository.FirstOrDefaultAsync(m => m.ID == request.ID);
            if (user == null)
            {
                return UnaryResult.Faild(10, "用户不存在");
            }

            user.U_NickName = request.U_NickName;
            user.U_RealName = request.U_RealName;
            user.ProvinceID = request.ProvinceID ?? user.ProvinceID;
            user.CityID = request.CityID ?? user.CityID;
            user.DistrictID = request.DistrictID ?? user.DistrictID;
            user.U_P_Name = request.U_P_Name ?? user.U_P_Name;
            user.U_C_Name = request.U_C_Name ?? user.U_C_Name;
            user.U_D_Name = request.U_D_Name ?? user.U_D_Name;
            user.U_Birthday = request.U_Birthday ?? user.U_Birthday;
            user.U_Sex = request.U_Sex;
            await _baseUserRepository.UpdateAsync(user);

            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        public async Task<PageResult<BaseUserDto>> PageListAsync(BaseUserPageRequestDto model)
        {
            var queryable = from user in _baseUserRepository.AsNoTracking()
                            join tennis1 in _baseUserExtendInfoRepository.AsNoTracking()
                            on user.ID equals tennis1.ID into tennis1d
                            from tennis1 in tennis1d.DefaultIfEmpty()
                            join tennis2 in _baseUserTennisLevelConfigRepository.AsNoTracking()
                            on tennis1.BaseUserTennisLevelConfigID equals tennis2.ID into tennis2d
                            from tennis2 in tennis2d.DefaultIfEmpty()
                            select new BaseUserDto
                            {
                                ID = user.ID,
                                U_Code = user.U_Code,
                                U_NickName = user.U_NickName,
                                U_Headportrait = user.U_Headportrait,
                                U_RealName = user.U_RealName,
                                U_OpenId = user.U_OpenId,
                                U_Unionid = user.U_Unionid,
                                U_PhoneNum = user.U_PhoneNum,
                                U_IsCanWithdrawal = user.U_IsCanWithdrawal,
                                U_Sex = user.U_Sex,
                                U_WxOpenId = user.U_WxOpenId,
                                CardName = user.CardName,
                                TennisLevel = tennis2.LevelName ?? "1.0",
                                CreateTime = user.CreateTime,
                            };
            if (!string.IsNullOrWhiteSpace(model.Key))
            {
                int.TryParse(model.Key, out var userCode);
                queryable = queryable.Where(m => m.U_Code == userCode || m.U_PhoneNum.Contains(model.Key));
            }

            var pageResult = await queryable.OrderByDescending(m => m.CreateTime).PageListAsync(model);
            return pageResult;
        }

        /// <summary>
        /// 用户实名认证
        /// </summary>
        public async Task<UnaryResult> AuthenticateIDAsync(BaseUserAuthorizeRequestDto request)
        {
            var user = await _baseUserRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == _currentInfo.UserId);
            if (user == null)
            {
                return UnaryResult.Faild(10, "用户不存在");
            }

            var builder = await _baseUserRepository.UpdatePartialAsync();
            builder = builder.Set(m => m.CardName, request.RealName).Where(m => m.ID == user.ID);
            await builder.ExecuteAsync();

            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 用户微信openid认证，获取微信认证url
        /// </summary>
        public async Task<UnaryResult<string>> AuthenticateWxOpenIdAsync()
        {
            var user = await _baseUserRepository.FirstOrDefaultAsync(m => m.ID == _currentInfo.UserId);
            var uscode = user.U_Code.ToString();
            var url = $"{_apiUrl.BaseUrl}v2/page/wx_authenticate?scope=snsapi_userinfo&attachData={uscode}";
            return UnaryResult.Succeed(url);
        }

        /// <summary>
        /// 获取用户网球水平
        /// </summary>
        /// <param name="userId">用户ID</param>
        public async Task<TennisLevelInfoDto> GetTennisLevelAsync(Guid userId)
        {
            var queryable = from extend in _baseUserExtendInfoRepository.AsNoTracking()
                            join tennis in _baseUserTennisLevelConfigRepository.AsNoTracking()
                            on extend.BaseUserTennisLevelConfigID equals tennis.ID
                            where extend.ID == userId
                            select new TennisLevelInfoDto
                            {
                                UserId = extend.ID,
                                LevelName = tennis.LevelName ?? "1.0"
                            };
            var result = await queryable.FirstOrDefaultAsync();
            result ??= new TennisLevelInfoDto { UserId = userId, LevelName = "1.0" };
            return result;
        }
    }
}
